﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Globalization;
using GMap.NET;
using GMap.NET.WindowsForms;
using GMap.NET.WindowsForms.Markers;
using GMap.NET.MapProviders;

namespace IS2
{
    public partial class AreaDeRiesgoForm : Form
    {
        // layers
        readonly GMapOverlay top = new GMapOverlay();
        internal readonly GMapOverlay polygons = new GMapOverlay("polygons");
        internal readonly GMapOverlay objects = new GMapOverlay("objects");
        // marker
        GMarkerGoogle currentMarker;

        // polygons
        GMapPolygon polygon;

        // etc
        readonly Random rnd = new Random();
        //readonly DescendingComparer ComparerIpStatus = new DescendingComparer();
        GMapMarkerRect CurentRectMarker = null;
        string mobileGpsLog = string.Empty;
        bool isMouseDown = false;
        PointLatLng start;
        PointLatLng end;

      
        List<FactorConMonitoreo> listaFactoresMonitoreo;
        public AreaDeRiesgos nuevaArea { get; set; }



        public AreaDeRiesgoForm()
        {
            InitializeComponent();
            cargarDatos();
            dataGridViewFactores.RowHeadersVisible = false;
            dataGridViewFactores.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
            dataGridViewFactores.AutoGenerateColumns = false;
            comboBoxNivelCapacitacion.SelectedIndex = 0;
            
        }

        




        private void Form1_Load(object sender, EventArgs e)
        {
            splitContainer1.Panel2Collapsed = true;
            this.Size = new Size(356, 658);
            MapContainer.MapProvider = GMap.NET.MapProviders.GoogleMapProvider.Instance;
            GMap.NET.GMaps.Instance.Mode = GMap.NET.AccessMode.ServerOnly;
            MapContainer.Position = new PointLatLng(-34.9036714018596, -56.1908197402954);
            MapContainer.MinZoom = 0;
            MapContainer.MaxZoom = 24;
            MapContainer.Zoom = 16;  
        

            //textBoxLat.Text = MapContainer.Position.Lat.ToString(CultureInfo.InvariantCulture);
            //textBoxLng.Text = MapContainer.Position.Lng.ToString(CultureInfo.InvariantCulture);

            MapContainer.OnPositionChanged += new PositionChanged(MainMap_OnPositionChanged);
            MapContainer.MouseMove += new MouseEventHandler(MainMap_MouseMove);
            MapContainer.MouseDown += new MouseEventHandler(MainMap_MouseDown);
            MapContainer.MouseUp += new MouseEventHandler(MainMap_MouseUp);
            MapContainer.MouseDoubleClick += new MouseEventHandler(MainMap_MouseDoubleClick);
            MapContainer.OnMapZoomChanged += new MapZoomChanged(MainMap_OnMapZoomChanged);
            MapContainer.OnMarkerClick += new MarkerClick(MainMap_OnMarkerClick);
            
            currentMarker = new GMarkerGoogle(MapContainer.Position, GMarkerGoogleType.arrow);
            currentMarker.IsHitTestVisible = false;
            top.Markers.Add(currentMarker);

            trackBar.Minimum = MapContainer.MinZoom * 100;
            trackBar.Maximum = MapContainer.MaxZoom * 100;
            trackBar.TickFrequency = 100;

            // add custom layers  
            {

                MapContainer.Overlays.Add(polygons);
                MapContainer.Overlays.Add(objects);
                MapContainer.Overlays.Add(top);

                
                objects.Markers.CollectionChanged += new GMap.NET.ObjectModel.NotifyCollectionChangedEventHandler(Markers_CollectionChanged);
            }

            
            nuevaArea = new AreaDeRiesgos();
            nuevaArea.ListaFactores = new List<FactorConMonitoreo>();
            cargarAreasDelimitadas();
           


        }

        private void MapContainer_MouseClick(object sender, MouseEventArgs e)
        {
            
        }

        void MainMap_OnPositionChanged(PointLatLng point)
        {
            //textBoxLat.Text = point.Lat.ToString(CultureInfo.InvariantCulture);
            //textBoxLng.Text = point.Lng.ToString(CultureInfo.InvariantCulture);

           
        }

        void MainMap_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left && isMouseDown)
            {
                if (CurentRectMarker == null)
                {
                    if (currentMarker.IsVisible)
                    {
                        currentMarker.Position = MapContainer.FromLocalToLatLng(e.X, e.Y);
                    }
                }
                else // move rect marker
                {
                    PointLatLng pnew = MapContainer.FromLocalToLatLng(e.X, e.Y);

                    int? pIndex = (int?)CurentRectMarker.Tag;
                    if (pIndex.HasValue)
                    {
                        if (pIndex < polygon.Points.Count)
                        {
                            polygon.Points[pIndex.Value] = pnew;
                            MapContainer.UpdatePolygonLocalPosition(polygon);
                        }
                    }

                    if (currentMarker.IsVisible)
                    {
                        currentMarker.Position = pnew;
                    }
                    CurentRectMarker.Position = pnew;

                    if (CurentRectMarker.InnerMarker != null)
                    {
                        CurentRectMarker.InnerMarker.Position = pnew;
                    }
                }

                MapContainer.Refresh(); // force instant invalidation
            }
        }

        void MainMap_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                isMouseDown = true;

                if (currentMarker.IsVisible)
                {
                    currentMarker.Position = MapContainer.FromLocalToLatLng(e.X, e.Y);

                    var px = MapContainer.MapProvider.Projection.FromLatLngToPixel(currentMarker.Position.Lat, currentMarker.Position.Lng, (int)MapContainer.Zoom);
                    var tile = MapContainer.MapProvider.Projection.FromPixelToTileXY(px);
                    txtLat.Text = currentMarker.Position.Lat.ToString();
                    txtLon.Text = currentMarker.Position.Lng.ToString();
                    //Debug.WriteLine("MouseDown: geo: " + currentMarker.Position + " | px: " + px + " | tile: " + tile);
                }
            }
        }

        void MainMap_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                isMouseDown = false;
            }
        }

        void MainMap_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            //var cc = new GMapMarkerRect(MapContainer.FromLocalToLatLng(e.X, e.Y));
            //objects.Markers.Add(cc);
            //MapContainer.Zoom = MapContainer.Zoom + 0.1;
            
        }

        void MainMap_OnMapZoomChanged()
        {
            trackBar.Value = (int)(MapContainer.Zoom * 100.0);
            textBoxZoomCurrent.Text = MapContainer.Zoom.ToString();
        }

        private void trackBar_ValueChanged(object sender, EventArgs e)
        {
            MapContainer.Zoom = trackBar.Value / 100.0;
        }


    
        void RegeneratePolygon()
        {
            List<PointLatLng> polygonPoints = new List<PointLatLng>();

            foreach (GMapMarker m in objects.Markers)
            {
                if (m is GMapMarkerRect)
                {
                    m.Tag = polygonPoints.Count;
                    polygonPoints.Add(m.Position);
                }
            }

            if (polygon == null)
            {
                polygon = new GMapPolygon(polygonPoints, "polygon test");
                polygon.IsHitTestVisible = true;
                polygons.Polygons.Add(polygon);
            }
            else
            {
                polygon.Points.Clear();
                polygon.Points.AddRange(polygonPoints);

                if (polygons.Polygons.Count == 0)
                {
                    polygons.Polygons.Add(polygon);
                }
                else
                {
                    MapContainer.UpdatePolygonLocalPosition(polygon);
                }
            }
        }

        void MainMap_OnMarkerClick(GMapMarker item, MouseEventArgs e)
        {
            if (e.Button == System.Windows.Forms.MouseButtons.Left)
            {
                if (item is GMapMarkerRect)
                {
                    GeoCoderStatusCode status;
                    var pos = GMapProviders.GoogleMap.GetPlacemark(item.Position, out status);
                    if (status == GeoCoderStatusCode.G_GEO_SUCCESS && pos != null)
                    {
                        GMapMarkerRect v = item as GMapMarkerRect;
                        {
                            v.ToolTipText = pos.Value.Address;
                        }
                        MapContainer.Invalidate(false);
                    }
                }
               /* else
                {
                    if (item.Tag != null)
                    {
                        if (currentTransport != null)
                        {
                            currentTransport.ToolTipMode = MarkerTooltipMode.OnMouseOver;
                            currentTransport = null;
                        }
                        currentTransport = item;
                        currentTransport.ToolTipMode = MarkerTooltipMode.Always;
                    }
                }*/
            }
        }
        void Markers_CollectionChanged(object sender, GMap.NET.ObjectModel.NotifyCollectionChangedEventArgs e)
        {
            //textBoxMarkerCount.Text = objects.Markers.Count.ToString();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            GMarkerGoogle m = new GMarkerGoogle(currentMarker.Position, GMarkerGoogleType.green_dot);
            GMapMarkerRect mBorders = new GMapMarkerRect(currentMarker.Position);
            {
                mBorders.InnerMarker = m;
                if (polygon != null)
                {
                    mBorders.Tag = polygon.Points.Count;
                }
                mBorders.ToolTipMode = MarkerTooltipMode.Always;
            }

            Placemark? p = null;
            // if (checkBoxPlacemarkInfo.Checked)
            //{
            GeoCoderStatusCode status;
            var ret = GMapProviders.GoogleMap.GetPlacemark(currentMarker.Position, out status);
            if (status == GeoCoderStatusCode.G_GEO_SUCCESS && ret != null)
            {
                p = ret;
            }
            //}

            if (p != null)
            {
                mBorders.ToolTipText = p.Value.Address;
            }
            else
            {
                mBorders.ToolTipText = currentMarker.Position.ToString();
            }

            objects.Markers.Add(m);
            objects.Markers.Add(mBorders);

            RegeneratePolygon();
            txtLat.Text = m.Position.Lat.ToString();
            txtLon.Text = m.Position.Lng.ToString();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            FactorDeRiesgoForm v = new FactorDeRiesgoForm(this);
            v.ShowDialog();
            v.Dispose();


            dataGridViewFactores.DataSource = null;
            dataGridViewFactores.DataSource = nuevaArea.ListaFactores;
            
            
          

        }


        private void cargarDatos()
        {
            /*using (Model1Container ctx = new Model1Container())
            {
                listaFactoresMonitoreo = (from f in ctx.
                                 select f).ToList<FactorDeRiesgo>() ;

            }*/
        }

        private void MapContainer_Load(object sender, EventArgs e)
        {

        }

        private void button3_Click(object sender, EventArgs e)
        {
            int cantMarkers = 0;
            int cantAccesos = 0;
            foreach (GMapMarker m in objects.Markers)
            {
                if (!(m is  GMapMarkerRect))
                {
                    if (m.Tag != null && m.Tag.ToString() == "acceso")
                        cantAccesos++;
                    else
                        cantMarkers++;
                }
            }

            if (cantMarkers > 2 && cantAccesos > 0)
            {
                AreaDelimitadaForm aDialog = new AreaDelimitadaForm();
                aDialog.ShowDialog();
                string nombre = aDialog.nombre;
                aDialog.Dispose();
                using (Model1Container ctx = new Model1Container())
                {
                    AreaGeografica a = new AreaGeografica();
                    a.Nombre = nombre;
                    foreach (GMapMarker m in objects.Markers)
                    {
                        Coordenada c = new Coordenada();
                        c.lat = m.Position.Lat;
                        c.lng = m.Position.Lng;
                        if (m.Tag != null && m.Tag.ToString() == "acceso")
                            a.ListaAccesos.Add(c);
                        else
                            a.ListaCoordenadas.Add(c);
                    }
                    ctx.AddToAreaGeograficaSet(a);
                    ctx.SaveChanges();

                }
                cargarAreasDelimitadas();
                objects.Markers.Clear();
                RegeneratePolygon();
            }
            else
            {
                MessageBox.Show("Debe ingresar al menos 3 puntos para formar un área y al menos 1 punto de acceso");
            }
        }

        private void cargarAreasDelimitadas()
        {
            using (Model1Container ctx = new Model1Container())
            {
                List<AreaGeografica> lista = (from a in ctx.AreaGeograficaSet.Include("ListaCoordenadas").Include("ListaAccesos")
                            select a).ToList<AreaGeografica>();
                
                comboBoxAreas.DataSource = lista;
                comboBoxAreas.DisplayMember = "Nombre";
                //if (comboBoxAreas.Items.Count > 1)
                 //   comboBoxAreas.SelectedIndex = 0;

            }
        }

        private void comboBoxAreas_SelectedValueChanged(object sender, EventArgs e)
        {
            objects.Markers.Clear();
            RegeneratePolygon();
            AreaGeografica a = (AreaGeografica)comboBoxAreas.SelectedItem;
            if (a != null)
            {
                foreach (Coordenada c in a.ListaCoordenadas)
                {
                    PointLatLng p = new PointLatLng(c.lat, c.lng);
                    GMarkerGoogle m = new GMarkerGoogle(p, GMarkerGoogleType.green_dot);
                    objects.Markers.Add(m);
                    GMapMarkerRect mBorders = new GMapMarkerRect(p);
                    {
                        mBorders.InnerMarker = m;
                        if (polygon != null)
                        {
                            mBorders.Tag = polygon.Points.Count;
                        }

                    }
                    objects.Markers.Add(mBorders);
                }
                foreach (Coordenada c in a.ListaAccesos)
                {
                    PointLatLng p = new PointLatLng(c.lat, c.lng);
                    GMarkerGoogle m = new GMarkerGoogle(p, GMarkerGoogleType.red_pushpin);
                    objects.Markers.Add(m);
                   
                }



                nuevaArea.AreaGeografica = a;

                RegeneratePolygon();
            }
        }

        private void button4_Click(object sender, EventArgs e)
        {
            objects.Markers.Clear();
            txtLat.Text = "";
            txtLon.Text = "";
            RegeneratePolygon();
        }

        private void button5_Click(object sender, EventArgs e)
        {
            

            using (Model1Container ctx = new Model1Container())
            {
                string Identificador = txtIDAreaRiesgo.Text;
                AreaDeRiesgo ar = (from a in ctx.AreaDeRiesgoSet
                                  where a.Identificador == Identificador
                                  select a).SingleOrDefault();

                if (ar != null)
                {
                    DialogResult dialogResult = MessageBox.Show("Existe un Área de Riesgo con el mismo identificador. ¿Desea guardar este Área de Riesgo con otro identificador?", null, MessageBoxButtons.YesNo);
                    if (dialogResult == DialogResult.Yes)
                    {
                        txtIDAreaRiesgo.Text = "AR_" + (ar.Id +1).ToString();
                    }
                    else if (dialogResult == DialogResult.No)
                    {
                        MessageBox.Show("Alta de Área de Riesgo cancelada.");
                        this.Dispose();
                    }
                }
                else
                {
                    string nombre = txtNombreAreaRiesgo.Text;
                    AreaDeRiesgo ar1 = (from a in ctx.AreaDeRiesgoSet
                                        where a.Nombre == nombre
                                       select a).SingleOrDefault();

                    if (ar1 != null)
                    {
                        DialogResult dialogResult = MessageBox.Show("Existe un Área de Riesgo con el mismo nombre. ¿Desea guardar este Área de Riesgo con otro nombre?", null, MessageBoxButtons.YesNo);
                        if (dialogResult == DialogResult.Yes)
                        {
                            txtNombreAreaRiesgo.Text = "";
                        }
                        else if (dialogResult == DialogResult.No)
                        {
                            MessageBox.Show("Alta de Área de Riesgo cancelada.");
                            this.Dispose();
                        }
                    }
                    else
                    {


                        AreaDeRiesgo a = new AreaDeRiesgo();
                        //a.AreaGeografica = nuevaArea.AreaGeografica;
                        a.Capacitacion = comboBoxNivelCapacitacion.SelectedItem.ToString();
                        a.Nombre = txtNombreAreaRiesgo.Text;
                        a.Identificador = txtIDAreaRiesgo.Text;
                        a.Planta = txtPlanta.Text;
                        a.Sector = txtSector.Text;
                        a.Orientacion = txtOrientacion.Text;
                        //foreach (FactorConMonitoreo f in nuevaArea.ListaFactores)
                        //{
                        //    a.FactorConMonitoreo.Add(f);
                        //}
                        //ctx.AreaGeograficaSet.Attach(nuevaArea.AreaGeografica); 
                        ctx.AreaDeRiesgoSet.AddObject(a);
                        ctx.SaveChanges();
                        MessageBox.Show("Área de Riesgo creada correctamente");
                    }
                }
            }
            
        }

        private void btnPtosAcceso_Click(object sender, EventArgs e)
        {
            GMarkerGoogle m = new GMarkerGoogle(currentMarker.Position, GMarkerGoogleType.red_pushpin);
            m.Tag = "acceso";
           

           


            objects.Markers.Add(m);
           

            RegeneratePolygon();
            txtLatPto.Text = m.Position.Lat.ToString();
            txtLngPto.Text = m.Position.Lng.ToString();
        }

        private void button7_Click(object sender, EventArgs e)
        {
            mostrarMapa(true);
            this.CenterToScreen();
        }

        private void button8_Click(object sender, EventArgs e)
        {
            mostrarMapa(false);
            this.CenterToScreen();
        }

        private void mostrarMapa(bool enabled)
        {
            splitContainer1.Panel2Collapsed = false;
            this.Size = new Size(1106, 658);
            groupAccess.Enabled = enabled;
            groupCoords.Enabled = enabled;
            button3.Enabled = enabled;
        }

    }
}
